#include <stdlib.h>
#include <stdio.h>

#include "script_stack.h"
#include "script_memory.h"
#include "script_debug.h"

script_stack_t *script_stack_create(script_stack_destroy_flag forcs_destory_flag)
{
	script_stack_t *stack = script_calloc(1,sizeof(script_stack_t));

	stack->forcs_destroy = forcs_destory_flag;

	stack->size = STACK_DEFAULT_SIZE;
	stack->datas = script_calloc(sizeof(void*),stack->size);
	stack->scale = -1;

	return stack;
}

int script_stack_force_destroy(script_stack_t *stack)
{
	if(stack == NULL){
		return -1;
	}

	script_free(stack->datas);

	script_free(stack);
	return 0;
}

int script_stack_destroy(script_stack_t *stack)
{
	if(stack == NULL){
		return -1;
	}

	if(stack->forcs_destroy && stack->scale >= 0){
		return -1;
	}

	return	script_stack_force_destroy(stack);
}

int script_stack_num_get(script_stack_t *stack)
{
	if(stack == NULL){
		return STACK_ERROR_PARAM_NULL;
	}
	return stack->scale+1;
}

void *script_stack_Top(script_stack_t *stack)
{
	if(stack == NULL){
		return NULL;
	}
	if(stack->scale < 0){
		return NULL;
	}
	return stack->datas[stack->scale];
}

void *script_stack_Pop(script_stack_t *stack)
{
	if(stack == NULL){
		SCRIPT_DEBUG_ERR("%s stack is NULL", __func__);
		return NULL;
	}

	if(stack->scale < 0){
		return NULL;
	}

	void *res = stack->datas[stack->scale];
	stack->scale--;
	return res;
}

int script_stack_Push(script_stack_t *stack, void *data)
{
	if(stack == NULL){
		SCRIPT_DEBUG_ERR("%s stack is NULL", __func__);
		return STACK_ERROR_PARAM_NULL;
	}
	
	if(stack->scale+1 == stack->size){
		stack->size *= 2;
		stack->datas = script_realloc(stack->datas,stack->size*sizeof(void*));
	}

	stack->datas[++stack->scale] = data;
	
	return 0;
}

int script_stack_IsEmpty(script_stack_t *stack)
{
	if(stack == NULL){
		return 1;
	}

	return (stack->scale < 0);
}

void *script_stack_get(script_stack_t *stack,int num)
{
	if(stack == NULL || stack->scale < 0){
		SCRIPT_DEBUG_ERR("%s stack is NULL or stack->scale < 0", __func__);
		return NULL;
	}

	if(num < 0){
		int index = stack->scale + num + 1;
		if(index < 0){
			SCRIPT_DEBUG_WARN("%s stack is index < 0,  stack->scale:%d num:%d", __func__, stack->scale, num);
			return NULL;
		}
		return stack->datas[index];
	}else{
		if(num > stack->scale){
			SCRIPT_DEBUG_ERR("%s stack is num > stack->scale,  stack->scale:%d num:%d", __func__, stack->scale, num);
			return NULL;
		}
		return stack->datas[num];
	}
}

